#ifndef _MY_UTIL_
#define _MY_UTIL_

#include <iostream>
#include <string>
#include <fstream> //ifstream,ofstream
#include <sstream>
#include <memory>
#include <unistd.h>    //access
#include <sys/stat.h>  //stat
#include <sys/types.h> //mkdir
#include <jsoncpp/json/json.h>

namespace util
{
    // 文件工具类
    // 获取⽂件⼤⼩（属性）
    // 判断⽂件是否存在
    // 向⽂件写⼊数据
    // 从⽂件读取数据
    // 针对⽬录⽂件多⼀个创建⽬录
    class FileUtil
    {
    public:
        FileUtil(const std::string name) : _name(name)
        {
        }
        bool Exists() // 判断文件是否存在
        {
            // access的F_OK专门检测文件是否存在-----存在返回0，否则返回-1
            if (::access(_name.c_str(), F_OK) == 0)
                return true;
            else
                return false;
        }
        size_t Size() // 获取文件大小
        {
            if (this->Exists() == false)
            {
                std::cout << "file is not exists!" << std::endl;
                return -1;
            }
            // strect stat结构体用来保存文件的属性信息
            struct stat st;
            // int ret = stat(_name.c_str(),&st);
            if (stat(_name.c_str(), &st) == 0)
                return st.st_size;
            else
            {
                std::cout << "stat failed!" << std::endl;
                return -1;
            }
        }
        bool GetContent(std::string *body) // 获取文件数据到body中
        {
            std::ifstream ifs;
            // 以二进制方式打开文件
            ifs.open(_name, std::ios::binary);
            if (ifs.is_open() == false)
            {
                std::cout << "open-i file failed!" << std::endl;
                ifs.close();
                return false;
            }
            // 获取文件大小，来动态调整body空间
            size_t flen = this->Size();
            body->resize(flen);

            // 读取
            // ifs.read((char *)&body[0], flen);
            ifs.read(&(*body)[0], flen);
            if (ifs.good() == false)
            {
                std::cout << "read file content failed!" << std::endl;
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }
        bool SetContent(const std::string &body) // 向文件中写入数据
        {
            std::ofstream ofs;
            //
            ofs.open(_name, std::ios::binary);
            if (ofs.is_open() == false)
            {
                std::cout << "open-o file failed!" << std::endl;
                ofs.close();
                return false;
            }
            // 写入
            ofs.write(body.c_str(), body.size());
            if (ofs.good() == false)
            {
                std::cout << "write file content failed!" << std::endl;
                ofs.close();
                return false;
            }
            ofs.close();
            return true;
        }
        bool CreateDirectory() // 针对目录时创建目录
        {
            if (this->Exists())
            {
                std::cout << "file is exists!" << std::endl;
                return true;
            }
            ::mkdir(_name.c_str(), 0777);
            return true;
        }
        ~FileUtil()
        {
        }

    private:
        std::string _name; // 文件名称
    };

    // Json工具类
    // 主要实现 序列化 和 反序列化
    class JsonUtil
    {
    public:
        JsonUtil()
        {
        }

        static bool Serialize(const Json::Value &value, std::string *body) // 序列化
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());

            std::stringstream ss;
            if (sw->write(value, &ss) != 0)
            {
                std::cout << "Serialize error" << std::endl;
                return false;
            }
            *body = ss.str();
            return true;
        }

        static bool UnSerialize(const std::string &body, Json::Value *value) // 反序列化
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());

            std::string err;
            // bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), value, &err);
            // if (ret == false)
            if (cr->parse(body.c_str(), body.c_str() + body.size(), value, &err) == false)
            {
                std::cout << "UnSerialize error" << std::endl;
                return false;
            }
            return true;
        }
        ~JsonUtil()
        {
        }

    private:
    };
}

#endif
